/*
 *   Copyright 2021 zzh
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 *
 */

package com.aduib.boot.common.SPI;

import com.aduib.boot.common.SPI.SPIDefinition.SPIRole;
import com.aduib.boot.common.SPI.config.SpiPostProcessor;
import com.aduib.boot.common.SPI.metadata.ConstructorMetaData;
import com.aduib.boot.common.SPI.metadata.FieldMetaData;
import com.aduib.boot.common.SPI.metadata.MetaDataBuilder;
import com.aduib.boot.common.SPI.metadata.MethodMetaData;
import com.aduib.boot.common.compiler.Compiler;
import com.aduib.boot.common.compiler.support.SpiAdaptiveClassAsmCompiler;
import com.aduib.boot.common.concurrent.JctoolsHelper;
import com.aduib.boot.common.exception.CommonException;
import com.aduib.boot.common.json.JsonParser;
import com.aduib.boot.common.lang.Prioritized;
import com.aduib.boot.common.log.LOG;
import com.aduib.boot.common.proxy.ProxyFactory;
import com.aduib.boot.common.scanner.ClassPathScanner;
import com.aduib.boot.common.util.ArrayUtils;
import com.aduib.boot.common.util.ClassUtils;
import com.aduib.boot.common.util.MapUtils;
import com.aduib.boot.common.util.ObjectUtils;
import com.aduib.boot.common.util.ServiceLoaderUtils;
import com.aduib.boot.common.util.StrUtils;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Parameter;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.ServiceLoader;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.regex.Pattern;

import static com.aduib.boot.common.scanner.ClassPathScanner.SEPARATOR;
import static java.util.Arrays.asList;

/**
 * SPI注解-》标记一个接口为SPI组件
 * </br>
 * Wrapper注解 -》标记一个SPI接口的实现为包装类，包装SPI接口，通过构造器动态创建包含指定SPI接口实例的类，实现动态调用
 * </br>
 * Adaptive注解-》标记一个SPI接口或者接口的方法，当标记方法时，接口必须有SPI注解。通过编译器动态创建SPI接口实例，实现动态调用
 * </br>
 *
 * @description: SPILoder
 * @author: zzh
 * @date: 2021/9/18 14:43
 */
public class DefaultSPIFactory implements ConfigurableSPIFactory {

  private static final Pattern NAME_SEPARATOR = Pattern.compile("\\s*[,]+\\s*");

  private final ClassPathScanner classPathScanner = ClassPathScanner.build();

  /** SPI_DEFINITIONS */
  private final ConcurrentMap<Class<?>, List<SPIDefinition>> SPI_DEFINITIONS =
      JctoolsHelper.nonBlockingHashMap(4);
  /** */
  private final Map<Class<?>, Object> SPI_INSTANCES = JctoolsHelper.nonBlockingHashMap(4);

  private final Map<Class<?>, Object> SPI_ADAPTIVE_INSTANCES = JctoolsHelper.nonBlockingHashMap(4);

  @Deprecated
  private final Map<Class<?>,Class<?>> CACHED_ADAPTIVE_CLASS_MAP = JctoolsHelper.nonBlockingHashMap(4);

  // 运行时保存SPI名称与对应的SPI接口
  @Deprecated
  private final ConcurrentMap<String, Class<?>> cachedSpiNames =
      JctoolsHelper.nonBlockingHashMap(4);

  private final Map<String, CommonException> exceptions = new ConcurrentHashMap<>();

  /**
   * Record all unacceptable exceptions when using SPI
   */
  private final Set<String> unacceptableExceptions = JctoolsHelper.nonBlockingHashSet();

  private final ConcurrentMap<Class<?>, SPIRole> strategyMap = JctoolsHelper.nonBlockingHashMap(1);

  private Set<Class<?>> cachedWrapperClasses;

  private LoadStrategy[] strategies;

  private List<SpiPostProcessor> spiPostProcessorList;

  public DefaultSPIFactory() {
    this.strategies = loadLoadingStrategies();
    this.spiPostProcessorList = initSpiPostProcessorList();
    initInternalSpi();
  }

  /**
   * 添加LoadStrategy
   *
   * @param loadStrategyClass
   * @param spiRole
   */
  public void addLoadStrategyToMap(Class<?> loadStrategyClass, String spiRole) {
    strategyMap.put(loadStrategyClass, SPIRole.valueOf(spiRole));
  }

  /** 初始化LoadStrategyMap */
  private void initLoadStrategyMap() {
    strategyMap.put(SPIInternalLoadStrategy.class, SPIRole.INTERNAL_SPI);
    strategyMap.put(SPILoadStrategy.class, SPIRole.NORMAL_SPI);
    strategyMap.put(ServicesLoadStrategy.class, SPIRole.NORMAL_SERVICES);
  }

  /**
   * Load all {@link Prioritized prioritized} {@link LoadStrategy Loading Strategies} via {@link
   * ServiceLoader}
   *
   * @return non-null
   * @since 1.0.0
   */
  private LoadStrategy[] loadLoadingStrategies() {
    LoadStrategy[] loadStrategies = ServiceLoaderUtils.loadArray(LoadStrategy.class);
    initLoadStrategyMap();
    return loadStrategies;
  }

  private List<SpiPostProcessor> initSpiPostProcessorList() {
    return ServiceLoaderUtils.loadList(SpiPostProcessor.class);
  }

  private void initInternalSpi() {
    loadSpiClasses(ProxyFactory.class);
    loadSpiClasses(Compiler.class);
    loadSpiClasses(JsonParser.class);
  }

  public void addSpiPostProcessor(SpiPostProcessor spiPostProcessor) {
    spiPostProcessorList.add(spiPostProcessor);
  }

  public List<SpiPostProcessor> getSpiPostProcessorList() {
    return spiPostProcessorList;
  }

  /**
   * Get all {@link LoadStrategy Loading Strategies}
   *
   * @return non-null
   * @see LoadStrategy
   * @see Prioritized
   * @since 1.0.0
   */
  public List<LoadStrategy> getLoadingStrategies() {
    return asList(strategies);
  }

  public void setLoadingStrategies(LoadStrategy... strategies) {
    if (ArrayUtils.isNotEmpty(strategies)) {
      this.strategies = strategies;
    }
  }

  private CommonException findException(Class<?> spiInterfaceClass, String name) {
    StringBuilder buf =
        new StringBuilder("No such SPI " + spiInterfaceClass.getName() + " by name " + name);

    int i = 1;
    for (Map.Entry<String, CommonException> entry : exceptions.entrySet()) {
      if (entry.getKey().toLowerCase().startsWith(name.toLowerCase())) {
        if (i == 1) {
          buf.append(", possible causes: ");
        }
        buf.append("\r\n(");
        buf.append(i++);
        buf.append(") ");
        buf.append(entry.getKey());
        buf.append(":\r\n");
        buf.append(StrUtils.toString(entry.getValue()));
      }
    }

    if (i == 1) {
      buf.append(
          ", no related exception was found, please check whether related SPI module is missing.");
    }
    return new CommonException(buf.toString());
  }

  /** cache wrapper class */
  private void cacheWrapperClass(Class<?> wrapperClass) {
    if (cachedWrapperClasses == null) {
      cachedWrapperClasses = JctoolsHelper.nonBlockingHashSet();
    }
    cachedWrapperClasses.add(wrapperClass);
  }

  /** test if clazz is a wrapper class */
  private boolean isWrapperClass(Class<?> spiInstanceClass, Class<?> spiInterfaceClass) {
    try {
      spiInstanceClass.getConstructor(spiInterfaceClass);
      return true;
    } catch (NoSuchMethodException e) {
      return false;
    }
  }

  /**
   * 通过spi对象获取SPI名称
   *
   * @param spiInstance
   * @return
   */
  private String getSpiNameBySpiInstance(Object spiInstance) {
    return getSpiNameBySpiInstance(spiInstance.getClass());
  }

  /**
   * 通过spi类型获取SPI名称
   *
   * @param spiClass
   * @return
   */
  private String getSpiNameBySpiInstance(Class<?> spiClass) {
    final String[] spiName = {null};
    List<SPIDefinition> spiDefinitions = getSPIDefinitionList(spiClass);
    if (spiDefinitions != null) {
      spiName[0] = createSpiName(spiClass);
    } else {
      SPI_DEFINITIONS.forEach(
          (spiInterface, spiInstances) -> {
            if (spiInterface.isAssignableFrom(spiClass)) {
              for (SPIDefinition spiDefinition : spiInstances) {
                if (spiDefinition.getSPIClass().equals(spiClass)) {
                  spiName[0] = spiDefinition.getName();
                }
              }
            }
          });
    }
    return spiName[0];
  }

  /**
   * Find the extension with the given name. If the specified name is not found, then {@link
   * CommonException} will be thrown.
   */

  /**
   * 获取SPIDefinition
   *
   * @param spiClass 接口类或者接口的实例
   * @param spiName
   * @return
   */
  private SPIDefinition doGetSpiDefinition(Class<?> spiClass, String spiName) {
    List<SPIDefinition> spiDefinitions = getSPIDefinitionList(spiClass);
    if (Objects.isNull(spiDefinitions) || spiDefinitions.isEmpty()) {
      throw new CommonException(
          "SPI (name: "
              + spiName
              + ", class: "
              + spiClass
              + ") couldn't be found SPIDefinition");
    }
    SPIDefinition definition = null;
    for (SPIDefinition spiDefinition : spiDefinitions) {
      if (spiDefinition.getName().equalsIgnoreCase(spiName)) {
        definition = spiDefinition;
      }
    }
    //指定的spi名称为空，才获取默认的spi定义
    if (Objects.isNull(definition)&&StrUtils.isBlank(spiName)) {
      for (SPIDefinition spiDefinition : spiDefinitions) {
        // 获取SPI接口上的默认配置
        String name = createSpiName(spiClass);
        if (StrUtils.isBlank(name)) {
          name = createSpiName(spiClass, spiDefinition.getSPIClass());
        }
        if (spiDefinition.getName().equalsIgnoreCase(name)) {
          definition = spiDefinition;
        }
      }
    }

    return definition;
  }

  /**
   * 获取SpiDefinition
   *
   * @param spiClass 接口类或者接口的实例
   * @param spiName
   * @return
   */
  private SPIDefinition getSpiDefinition(Class<?> spiClass, String spiName) {
    SPIDefinition spiDefinition = null;
    try {
      spiDefinition = doGetSpiDefinition(spiClass, spiName);
    } catch (Exception ex) {
      throw new CommonException(ex);
    }
    return spiDefinition;
  }


  /**
   * 获取接口的默认spi定义
   * @param spiInterfaceClass
   * @return
   */
  private SPIDefinition getDefaultSpiDefinition(Class<?> spiInterfaceClass) {
    SPIDefinition spiDefinition = null;
    try {
      spiDefinition = doGetSpiDefinition(spiInterfaceClass, StrUtils.EMPTY);
    } catch (Exception ex) {
      throw new CommonException(ex);
    }
    return spiDefinition;
  }

  /**
   * 获取AdaptiveSpiDefinition
   *
   * @param spiInterfaceClass
   * @return
   */
  private SPIDefinition getAdaptiveSpiDefinition(Class<?> spiInterfaceClass) {
    SPIDefinition spiDefinition = null;
    try {
      spiDefinition = doGetSpiDefinition(spiInterfaceClass, createAdaptiveSpiName(spiInterfaceClass));
    } catch (Exception ex) {
      throw new CommonException(ex);
    }
    return spiDefinition;
  }

  /**
   * 获取SPIDefinition列表，没有数据返回空列表
   *
   * @param spiClass
   * @return
   */
  @SuppressWarnings("unchecked")
  private List<SPIDefinition> getSPIDefinitionList(Class<?> spiClass) {
    Class<?> interfaceClass = getInterfaceClass(spiClass);
    List<SPIDefinition> spiDefinitions = SPI_DEFINITIONS.get(interfaceClass);
    return Objects.isNull(spiDefinitions) ? new ArrayList<>() : spiDefinitions;
  }

  /**
   * 寻找接口 (不稳定方法，可能出现bug)
   *
   * @param spiInstanceClass
   * @return
   */
  private Class<?> getInterfaceClass(Class<?> spiInstanceClass) {
    Class<?> superclass = null;
    Class<?>[] interfaces = spiInstanceClass.getInterfaces();
    if (interfaces != null && interfaces.length > 0) {
      for (Class<?> anInterface : interfaces) {
        if (anInterface.isAssignableFrom(spiInstanceClass) && FactoryUtils.withSpiAnnotation(anInterface)) {
          superclass = anInterface;
          break;
        }
      }
    }
    // 没有父类或者实现接口 返回原来的类型
    if (Objects.isNull(superclass)) {
      return spiInstanceClass;
    }
    return superclass;
  }

  @Deprecated
  private Class<?> getSuperclass(Class<?> spiInstanceClass) {
    Class<?> superclass = spiInstanceClass.getSuperclass();
    if (superclass != null
        && !Object.class.equals(superclass)
        && superclass.isAssignableFrom(spiInstanceClass)) {
      return superclass;
    }
    // 没有父类或者实现接口 返回原来的类型
    if (Objects.isNull(superclass)) {
      return spiInstanceClass;
    }
    return superclass;
  }

  /**
   * 寻找构造器元数据
   * @param spiDefinition
   * @return
   */
  private ConstructorMetaData getConstructor(SPIDefinition spiDefinition) {
    Class<?> spiInstanceClass = spiDefinition.getSPIClass();
    String spiName = spiDefinition.getName();

    List<ConstructorMetaData> constructorMetaDataList = spiDefinition.getConstructorMetaDataList();
    ConstructorMetaData defaultConstructor = null;
    // 寻找默认构造器
    for (ConstructorMetaData constructor : constructorMetaDataList) {
      int parameterCount = constructor.getParameterCount();
      // 有参数构造器
      Class<?>[] parameters = constructor.getParameterTypes();
      int spiParameterCount = 0;
      for (Class<?> parameterType : parameters) {
        //排除jdk的API
        if (!ClassUtils.isJdk(parameterType)&&parameterCount>0) {
          // 加载参数所在的SPi配置
          if (!containSPIDefinition(parameterType)) {
            loadSpiClasses(parameterType);
          }
          if (!parameterType.isInterface()) {
            throwNoConstructorException(spiInstanceClass, spiName);
          }
          // 不能引用自身
          if (parameterType.equals(spiInstanceClass)) {
            throwNoConstructorException(spiInstanceClass, spiName);
          }
          // 循环引用问题
          judgeConstructorCircularReference(spiName, spiInstanceClass, parameterType);
          // 参数为接口类型
          Class<?> superclass = getInterfaceClass(parameterType);
          if (containSPIDefinition(superclass)) {
            // 参数是具体的spi类
            spiParameterCount++;
          } else if (containSPIDefinition(parameterType)) {
            // 参数在SPI定义中存在
            spiParameterCount++;
          } else {
            spiParameterCount--;
          }
        }
      }
      // 构造器参数个数与spi实例参数个数一致 不一致抛出异常，对于SPI类的有参数构造器的参数必须是SPI类型，否则只保留一个无参数的构造器
      if (spiParameterCount == parameterCount) {
        defaultConstructor = constructor;
        defaultConstructor.setParameterValues(MetaDataBuilder.buildParameterValues(constructor, this));
        break;
      }
    }
    if (Objects.isNull(defaultConstructor) || Objects.isNull(defaultConstructor.getAccessibleObject())) {
      defaultConstructor = MetaDataBuilder.getZeroArgsConstructor(constructorMetaDataList);
    }
    if (Objects.isNull(defaultConstructor) || Objects.isNull(defaultConstructor.getAccessibleObject())) {
      throwNoConstructorException(spiInstanceClass, spiName);
    }
    return defaultConstructor;
  }
  /**
   * 获取构造器 构造器参数建议是接口类型，参数名对应SPI名
   *
   * @param spiInstanceClass
   * @param spiName
   * @return
   */
  @Deprecated
  private ConstructorInjectMetaData getConstructor(Class<?> spiInstanceClass, String spiName) {
    Constructor<?>[] constructors = ClassUtils.getConstructors(spiInstanceClass);
    Constructor<?> defaultConstructor = null;
    List<ParameterInjectMetaData> pimd = new ArrayList<>();
    // 寻找默认构造器
    for (Constructor<?> constructor : constructors) {
      int parameterCount = constructor.getParameterCount();
      // 默认无参数构造器
      if (parameterCount == 0) {
        defaultConstructor = constructor;
        break;
      }
    }
    if (Objects.isNull(defaultConstructor)) {
      for (Constructor<?> constructor : constructors) {
        int parameterCount = constructor.getParameterCount();
        // 默认无参数构造器
        if (parameterCount == 0) {
          defaultConstructor = constructor;
          break;
        } else {
          // 有参数构造器
          Parameter[] parameters = constructor.getParameters();
          for (Parameter parameter : parameters) {
            Class<?> parameterType = parameter.getType();
            // 加载参数所在的SPi配置
            if (!containSPIDefinition(parameterType)) {
              loadSpiClasses(parameterType);
            }
            if (!parameterType.isInterface()) {
              throwNoConstructorException(spiInstanceClass, spiName);
            }
            // 不能引用自身
            if (parameterType.equals(spiInstanceClass)) {
              throwNoConstructorException(spiInstanceClass, spiName);
            }
            // 循环引用问题
//            judgeConstructorCircularReference(spiName, spiInstanceClass, parameterType);
            // 参数为具体类型
            Class<?> superclass = getInterfaceClass(parameterType);
            if (containSPIDefinition(superclass)) {
              // 参数是具体的spi类
              pimd.add(new ParameterInjectMetaData(superclass, createSpiName(superclass)));
            } else if (containSPIDefinition(parameterType)) {
              // 参数在SPI定义中存在
              pimd.add(new ParameterInjectMetaData(parameterType, createSpiName(parameterType)));
            } else {
              pimd.clear();
            }
          }
          // 构造器参数个数与spi实例参数个数一致 不一致抛出异常，对于SPI类的有参数构造器的参数必须是SPI类型，否则只保留一个无参数的构造器
          if (pimd.size() == parameterCount) {
            defaultConstructor = constructor;
            break;
          }
        }
      }
    }
    if (Objects.isNull(defaultConstructor)) {
      throwNoConstructorException(spiInstanceClass, spiName);
    }
    return new ConstructorInjectMetaData(defaultConstructor, pimd, ArrayUtils.EMPTY_OBJECT_ARRAY);
  }

  /**
   * @param wrapperSpiDefinition
   * @param spiDefinition
   * @return
   */
  private ConstructorMetaData getWrapConstructor(SPIDefinition wrapperSpiDefinition, SPIDefinition spiDefinition) {
    String spiName=spiDefinition.getName();
    Class<?> spiInstanceClass=spiDefinition.getSPIClass();

    Class<?> wrapClass=wrapperSpiDefinition.getSPIClass();
    String wrapperSpiName = wrapperSpiDefinition.getName();
    // wrapper的所有构造器
    List<ConstructorMetaData> constructorMetaDataList = wrapperSpiDefinition.getConstructorMetaDataList();
    // wrap类必须是有一个有参数构造器,构造器参数一个
    if (constructorMetaDataList.size() > 1) {
      throwNoConstructorException(wrapClass, wrapperSpiName);
    }

    ConstructorMetaData constructorMetaData = null;
//    List<ParameterInjectMetaData> pimd = new ArrayList<>();
    for (ConstructorMetaData constructor : constructorMetaDataList) {
      if (constructor.getParameterCount() == 1) {
        for (Class<?> parameterType : constructor.getParameterTypes()) {
          // 不能引用自身
          if (parameterType.equals(wrapClass)) {
            throwNoConstructorException(wrapClass, spiName);
          }
          // 判断构造器参数类型是当前wrapper类的父类或者实现的接口
          if (!parameterType.isAssignableFrom(wrapClass)) {
            throwNoConstructorException(wrapClass, spiName);
          }
          // 构造器参数与spi实例有关
          if (parameterType.isAssignableFrom(spiInstanceClass)) {
            constructorMetaData = constructor;
            break;
          }
        }
      }
    }
    if (Objects.isNull(constructorMetaData) || Objects.isNull(constructorMetaData.getAccessibleObject())) {
      throwNoConstructorException(wrapClass, spiName);
    }
    return constructorMetaData;
  }

  /**
   * @param wrapClass
   * @param spiName
   * @param wrapClass
   * @return
   */
  @Deprecated
  private ConstructorInjectMetaData getWrapConstructor(
      Class<?> wrapClass, String spiName, Class<?> spiInstanceClass) {
    // wrapper的所有构造器
    Constructor<?>[] constructors = ClassUtils.getConstructors(wrapClass);

    Constructor<?> defaultConstructor = null;
    List<ParameterInjectMetaData> pimd = new ArrayList<>();
    // wrap类必须是有一个有参数构造器,构造器参数一个
    if (constructors.length > 1) {
      throwNoConstructorException(wrapClass, spiName);
    }
    for (Constructor<?> constructor : constructors) {
      Parameter[] parameters = constructor.getParameters();
      if (parameters.length == 1) {
        for (Parameter parameter : parameters) {
          Class<?> parameterType = parameter.getType();
          // 不能引用自身
          if (parameterType.equals(wrapClass)) {
            throwNoConstructorException(wrapClass, spiName);
          }
          // 判断构造器参数类型是当前wrapper类的父类或者实现的接口
          if (!parameterType.isAssignableFrom(wrapClass)) {
            throwNoConstructorException(wrapClass, spiName);
          }
          // 构造器参数与spi实例无关
          if (!spiInstanceClass.isAssignableFrom(parameterType)) {
            return null;
          }
          pimd.add(new ParameterInjectMetaData(parameterType, spiName));
          defaultConstructor = constructor;
          break;
        }
      }
    }
    if (Objects.isNull(defaultConstructor)) {
      throwNoConstructorException(wrapClass, spiName);
    }
    return new ConstructorInjectMetaData(defaultConstructor, pimd, ArrayUtils.EMPTY_OBJECT_ARRAY);
  }

  /**
   * 根据接口获取SPI列表
   *
   * @param spiInterfaceClass
   * @return
   */
  private Map<String, Class<?>> doGetSPIMap(Class<?> spiInterfaceClass) {
    Map<String, Class<?>> spiClasses = new HashMap<String, Class<?>>();
    if (!containSPIDefinition(spiInterfaceClass)) {
      loadSpiClasses(spiInterfaceClass);
    }
    List<SPIDefinition> spiDefinitions = getSPIDefinitionList(spiInterfaceClass);
    for (SPIDefinition spiDefinition : spiDefinitions) {
      spiClasses.put(spiDefinition.getName(), spiDefinition.getSPIClass());
    }
    return spiClasses;
  }

  /**
   *
   * @param spiClass 接口类型或者接口的实例
   * @param spiName
   * @param <T>
   * @return
   */
  private <T> T doGetSpi(Class<T> spiClass, String spiName) {
    return (T) doGetSpi(spiClass, spiName, true);
  }

  /**
   *
   * @param spiInterfaceClass 接口类型或者接口的实例
   * @param spiName
   * @param wrap
   * @return
   */
  @SuppressWarnings("unchecked")
  private <T> T doGetSpi(Class<T> spiInterfaceClass, String spiName, boolean wrap) {
    if (spiInterfaceClass == null) {
      throw new IllegalArgumentException("SPI type == null");
    }
    //兼容做法，如果不是接口类型，尝试获取标记SPI注解{@link com.aduib.boot.common.SPI.SPI}的接口
    spiInterfaceClass = (Class<T>) getInterfaceClass(spiInterfaceClass);
    if (!spiInterfaceClass.isInterface()) {
      throw new IllegalArgumentException(
          "SPI type (" + spiInterfaceClass + ") is not an interface!");
    }
    if (!FactoryUtils.withSpiAnnotation(spiInterfaceClass)) {
      throw new IllegalArgumentException(
          "SPI type ("
              + spiInterfaceClass
              + ") is not an SPI, because it is NOT annotated with @"
              + SPI.class.getSimpleName()
              + "!");
    }
    if (!containSPIDefinition(spiInterfaceClass)) {
      loadSpiClasses(spiInterfaceClass);
    }
    SPIDefinition spiDefinition = getSpiDefinition(spiInterfaceClass, spiName);
    Object spiInstance = createSpiInstance(spiDefinition);
    return (T) injectSpiWrapInstance(spiDefinition,injectSpiInstance(spiInstance,spiDefinition),wrap);
  }
  /**
   * 创建SPI实例
   *
   * @param definition
   * @return
   */
  private Object createSpiInstance(SPIDefinition definition) {
    Class<?> spiInstanceClass = definition.getSPIClass();
    //    Class<?> superclass = getSuperclass(spiInstanceClass);
    String spiName = definition.getName();
    if (definition == null || unacceptableExceptions.contains(spiName)) {
      throw findException(spiInstanceClass, spiName);
    }
    try {
      Object instance = SPI_INSTANCES.get(spiInstanceClass);
      if (instance == null) {
        List<Object> arguments = new ArrayList<>();

        ConstructorMetaData cimd = getConstructor(definition);
        Collections.addAll(arguments, cimd.getParameters());
//        Constructor<?> defaultConstructor = cimd.getConstructor();
//        List<ParameterInjectMetaData> metaDataList = cimd.getMetaDataList();
//        for (ParameterInjectMetaData metaData : metaDataList) {
//          // 实例化参数
//          SPIDefinition spiDefinitionParameter =
//              getSpiDefinition(metaData.getSpiClass(), metaData.getSpiName());
//          arguments.add(createSpiInstance(spiDefinitionParameter));
//        }
        Object newInstance = FactoryUtils.newSPIInstance(cimd);
//        Object newInstance = defaultConstructor.newInstance(arguments.toArray());
        newInstance = applyBeanPostProcessorsBeforeInitialization(newInstance, definition);
        SPI_INSTANCES.put(spiInstanceClass, newInstance);
        instance = SPI_INSTANCES.get(spiInstanceClass);
      }
      return instance;
    } catch (Throwable t) {
      throw new CommonException(
          "SPI instance (name: "
              + spiName
              + ", class: "
              + spiInstanceClass
              + ") couldn't be instantiated: "
              + t.getMessage(),
          t);
    }
  }

  /**
   * 判断SPI构造器的参数类型与SPI类型是否相互引用
   *
   * @param spiName
   * @param spiInstanceClass
   * @param parameterType
   */
  private void judgeConstructorCircularReference(
          String spiName, Class<?> spiInstanceClass, Class<?> parameterType) {
    // 避免循环依赖
    Constructor<?> parameterConstructor = null;
    SPIDefinition spiDefinition = getSpiDefinition(parameterType, createSpiName(parameterType));
    List<ConstructorMetaData> constructorMetaDataList = spiDefinition.getConstructorMetaDataList();
    for (ConstructorMetaData constructorMetaData : constructorMetaDataList) {
      if (constructorMetaData.getParameterCount() == 0) {
        parameterConstructor = null;
      } else {
        for (Class<?> type : constructorMetaData.getParameterTypes()) {
          if (type.isAssignableFrom(spiInstanceClass)
                  || type.equals(spiInstanceClass)) {
            parameterConstructor = (Constructor<?>) constructorMetaData.getAccessibleObject();
          }
        }
      }
    }
    if (Objects.nonNull(parameterConstructor)) {
      throwConstructorCircularReferenceException(spiInstanceClass, parameterType);
    }
  }

  /**
   * 构造器循环引用异常
   *
   * @param spiInstanceClass
   * @param parameterType
   */
  private void throwConstructorCircularReferenceException(
      Class<?> spiInstanceClass, Class<?> parameterType) {
    throw new CommonException(
        "SPI instance (class: "
            + spiInstanceClass
            + ") couldn't be instantiated: constructor circular reference class: "
            + parameterType);
  }

  /**
   * @param spiInstanceClass
   * @param spiName
   */
  private void throwNoConstructorException(Class<?> spiInstanceClass, String spiName) {
    throw new CommonException(
        "SPI instance (name: "
            + spiName
            + ", class: "
            + spiInstanceClass
            + ") couldn't be instantiated: dont have matched constructor");
  }

  /**
   * 对象注入
   * @param spi
   * @return
   */
  private Object doInjectSpi(Object spi,boolean wrap) {
    ObjectUtils.checkNotNull(spi,"spi对象为空");
    String name = getSpiNameBySpiInstance(spi);
    Class<?> spiClass = spi.getClass();
    if(!containSPIDefinition(spiClass,name)){
      throw new CommonException("current class: {} is not SPI Class",spiClass);
    }
    SPIDefinition spiDefinition = getSpiDefinition(spiClass,name);
    return injectSpiWrapInstance(spiDefinition,injectSpiInstance(spi,spiDefinition),wrap);
  }

  /**
   * 注入
   * @param spiInstance 需要初始化的对象
   * @param spiDefinition 对应的spi定义元数据
   * @return
   */
  private Object injectSpiInstance(Object spiInstance,SPIDefinition spiDefinition) {
    try {
      if (Objects.isNull(spiInstance)) {
        return spiInstance;
      }
      HashSet<Class<?>> hashSet = MapUtils.set(false);

      //填充属性
      List<FieldMetaData> fieldMetaDataList = spiDefinition.getFieldMetaDataList();
      for (FieldMetaData fieldMetaData : fieldMetaDataList) {
        Field field = (Field) fieldMetaData.getAccessibleObject();
        //不处理静态属性和final属性
        if (!ClassUtils.isStatic(field)&&!ClassUtils.isFinal(field)){
          Class<?> fieldType = fieldMetaData.getFieldType();
          String fieldName = fieldMetaData.getSimpleName();
          Object fieldValue = ClassUtils.getFieldValue(spiInstance, fieldName);

          /** Check {@link DisableInject} to see if we need auto injection for this property */
          if (fieldMetaData.getAnnotation(DisableInject.class) != null) {
            continue;
          }
          // 跳过javaAPI定义的参数类型
          Class<?> pt = fieldMetaData.getFieldType();
          if (ClassUtils.isPrimitiveWrapper(pt) || ClassUtils.isPrimitiveWrapperArray(pt)) {
            continue;
          }
          if(!FactoryUtils.withSpiAnnotation(pt)){
            continue;
          }
          //只对空值赋值
          if(Objects.isNull(fieldValue)){
            //获取SPI对象，填充属性
            ClassUtils.setFieldValue(spiInstance,fieldName,doGetSpi(fieldType,fieldName,true));

            hashSet.add(fieldType);
          }

        }
      }
      List<MethodMetaData> methodMetaDataList = spiDefinition.getMethodMetaDataList();
      for (MethodMetaData methodMetaData : methodMetaDataList) {
        Method method = (Method) methodMetaData.getAccessibleObject();
        if (!FactoryUtils.isSetter(methodMetaData)) {
          continue;
        }
        /** Check {@link DisableInject} to see if we need auto injection for this property */
        if (methodMetaData.getAnnotation(DisableInject.class) != null) {
          continue;
        }
        // 跳过javaAPI定义的参数类型,跳过已经注入的类型
        Class<?> pt = methodMetaData.getParameterTypes()[0];
        if (ClassUtils.isPrimitiveWrapper(pt) || ClassUtils.isPrimitiveWrapperArray(pt) || hashSet.contains(pt)) {
          continue;
        }
        if(!FactoryUtils.withSpiAnnotation(pt)){
          continue;
        }
        try {
          Object spi = doGetSpi(pt,getSpiNameBySpiInstance(pt),true);
          if (spi != null) {
            ClassUtils.invokeMethod(spiInstance,method, spi);
          }
        } catch (Exception e) {
          LOG.e(
                  "Failed to inject via method "
                          + method.getName()
                          + " of interface "
                          + spiInstance.getClass().getName()
                          + ": "
                          + e.getMessage(),
                  e);
        }
      }
    } catch (Exception e) {
      LOG.e(e.getMessage(), e);
    }
    return spiInstance;
  }
  /**
   * SPI实例注入
   *
   * @param spiInstance
   * @return
   */
  private Object injectSpiInstance(Object spiInstance) {
    try {
      if (Objects.isNull(spiInstance)) {
        return spiInstance;
      }
      for (Method method : spiInstance.getClass().getMethods()) {
        if (!isSetter(method)) {
          continue;
        }
        /** Check {@link DisableInject} to see if we need auto injection for this property */
        if (method.getAnnotation(DisableInject.class) != null) {
          continue;
        }
        // 跳过javaAPI定义的参数类型
        Class<?> pt = method.getParameterTypes()[0];
        if (ClassUtils.isPrimitiveWrapper(pt) || ClassUtils.isPrimitiveWrapperArray(pt)) {
          continue;
        }

        try {
          String property = getSetterProperty(method);
          Object object = doGetSpi(pt, property,true);
          if (object != null) {
            method.invoke(spiInstance, object);
          }
        } catch (Exception e) {
          LOG.e(
              "Failed to inject via method "
                  + method.getName()
                  + " of interface "
                  + spiInstance.getClass().getName()
                  + ": "
                  + e.getMessage(),
              e);
        }
      }
    } catch (Exception e) {
      LOG.e(e.getMessage(), e);
    }
    return spiInstance;
  }

  /**
   * SPI_Wrap注入
   *
   * @param spiDefinition
   * @param spiInstance
   * @param wrap
   * @return
   */
  private Object injectSpiWrapInstance(SPIDefinition spiDefinition, Object spiInstance, boolean wrap) {
    String spiName = spiDefinition.getName();
    if (spiName == null && !SPI_INSTANCES.containsValue(spiInstance)) {
      throw new CommonException("current object :[{}] is not a spiInstance", spiInstance);
    }
    try {
      if (wrap) {
        List<Class<?>> wrapperClassesList = new ArrayList<>();
        if (cachedWrapperClasses != null) {
          wrapperClassesList.addAll(cachedWrapperClasses);
          wrapperClassesList.sort(WrapperComparator.COMPARATOR);
          Collections.reverse(wrapperClassesList);
        }

        if (!wrapperClassesList.isEmpty()) {
          for (Class<?> wrapperClass : wrapperClassesList) {
            Wrapper wrapper = wrapperClass.getAnnotation(Wrapper.class);
            if (wrapper != null
                && (ArrayUtils.contains(wrapper.matches(), spiName)
                    && !ArrayUtils.contains(wrapper.mismatches(), spiName))) {

              /** 创建wrapper类元数据 */
              String wrapperSpiName = createWrapperSpiName(wrapperClass);
              Class<?> interfaceClass = getInterfaceClass(spiDefinition.getSPIClass());
              if (!containSPIDefinition(interfaceClass, wrapperSpiName, wrapperClass)) {
                doAddSpiDefinition(wrapperSpiName, wrapperClass);
              }

              SPIDefinition wrapperSpiDefinition = getSpiDefinition(interfaceClass, wrapperSpiName);
              if (Objects.nonNull(wrapperSpiDefinition)) {
                ConstructorMetaData constructorMetaData =
                    getWrapConstructor(wrapperSpiDefinition, spiDefinition);
                //                Constructor<?> defaultConstructor =
                // constructorMetaData.getConstructor();
                constructorMetaData.setParameterValues(new Object[]{spiInstance});
                Object wrapperSpiInstance = FactoryUtils.newSPIInstance(constructorMetaData);
                spiInstance = injectSpiInstance(wrapperSpiInstance,wrapperSpiDefinition);
              }
            }
          }
        }
      }
    } catch (Throwable t) {
      throw new CommonException(
              "SPI instance (name: "
                      + spiName
                      + ", class: "
                      + spiDefinition.getSPIClass()
                      + ") couldn't be injectSpiWrapInstance: "
              + t.getMessage(),
          t);
    }
    return spiInstance;
  }

  /**
   * get properties name for setter, for instance: setVersion, return "version"
   *
   * <p>return "", if setter name with length less than 3
   */
  private String getSetterProperty(Method method) {
    return method.getName().length() > 3
        ? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4)
        : "";
  }

  /**
   * return true if and only if:
   *
   * <p>1, public
   *
   * <p>2, name starts with "set"
   *
   * <p>3, only has one parameter
   */
  private boolean isSetter(Method method) {
    return method.getName().startsWith("set")
        && method.getParameterTypes().length == 1F
        && Modifier.isPublic(method.getModifiers());
  }

  private Class<?> getSpiClass(Class<?> spiInterfaceClass, String name) {
    if (spiInterfaceClass == null) {
      throw new IllegalArgumentException("SPI type == null");
    }
    if (name == null) {
      throw new IllegalArgumentException("SPI name == null");
    }
    return getSpiClasses(spiInterfaceClass).get(name);
  }

  /**
   * 获取当前线程的加载的SPI类型列表
   *
   * @param spiInterfaceClass
   * @return
   */
  @Deprecated
  private Map<String, Class<?>> getSpiClasses(Class<?> spiInterfaceClass) {
    if (SPI_DEFINITIONS.isEmpty()) {
      loadSpiClasses(spiInterfaceClass);
    }
    return doGetSPIMap(spiInterfaceClass);
  }

  private String createAdaptiveSpiName(Class<?> adaptiveInterfaceClass) {
    return ClassUtils.getClassName(adaptiveInterfaceClass,true) + "$$Adaptive";
  }

  private String createWrapperSpiName(Class<?> wrapperClass) {
    return ClassUtils.getClassName(wrapperClass,true) + "$$Wrapper";
  }

  /**
   * createSpiName
   *
   * @param spiInterface
   * @param spiInstanceClass
   * @return
   */
  @SuppressWarnings("deprecation")
  private String createSpiName(Class<?> spiInterface, Class<?> spiInstanceClass) {
    String name=createSpiName(spiInterface);
    if (StrUtils.isBlank(name)) {
      name = spiInstanceClass.getSimpleName();
      if (name.endsWith(spiInterface.getSimpleName())) {
        name = name.substring(0, name.length() - spiInterface.getSimpleName().length());
      }
    }
    return name.toLowerCase();
  }

  /** extract and cache default SPI name if exists */
  private String createSpiName(Class<?> spiInterface) {
    String name = spiInterface.getName();
    final SPI defaultAnnotation = spiInterface.getAnnotation(SPI.class);
    if (defaultAnnotation == null) {
      return "";
    }

    String value = defaultAnnotation.value();
    if ((value = value.trim()).length() > 0) {
      String[] names = NAME_SEPARATOR.split(value);
      if (names.length > 1) {
        throw new CommonException(
            "More than 1 default extension name on extension "
                + spiInterface.getName()
                + ": "
                + Arrays.toString(names));
      }
      if (names.length == 1) {
        name = names[0];
      }
    }
    return name;
  }

  /**
   * @param spiInterfaceClass
   * @param strategy
   * @return
   */
  @Deprecated
  private Map<String, Class<?>> loadSpiClasses(Class<?> spiInterfaceClass, LoadStrategy strategy) {
    String spiName = createSpiName(spiInterfaceClass);

    Map<String, Class<?>> spiClasses = new HashMap<>();

    loadDirectory(spiClasses, strategy, spiInterfaceClass);

    return spiClasses;
  }

  /**
   * @param spiInterfaceClass
   * @return
   */
  private synchronized Map<String, Class<?>> loadSpiClasses(Class<?> spiInterfaceClass) {
    String spiName = createSpiName(spiInterfaceClass);

//    cacheName(spiInterfaceClass, spiName);

    Map<String, Class<?>> spiClasses = new HashMap<>();
    if (containSPIDefinition(spiInterfaceClass)) {
      spiClasses = doGetSPIMap(spiInterfaceClass);
      return spiClasses;
    }

    LOG.d("starting load SPI classes with implements [ {} ]", spiInterfaceClass);
    for (LoadStrategy strategy : strategies) {
      // SPI配置文件集合
      try {
        classPathScanner.setFileSuffix(spiInterfaceClass.getName());
        // 根据策略偏好设置类加载器
        if (strategy.preferSpiClassLoader()) {
          ClassLoader spiFactoryClassLoader = SPIFactory.class.getClassLoader();
          classPathScanner.setClassLoader(spiFactoryClassLoader);
        }
        List<ClassPathScanner.Resource> SPIConfigPaths =
            classPathScanner.getResourceListByClassPath(strategy.directory());
        LOG.d("used  strategy [ {} ] search SPIConfig size: {} ", strategy, SPIConfigPaths.size());
        for (ClassPathScanner.Resource spiConfigUrl : SPIConfigPaths) {
          // 只加载包含策略路径的资源
          LOG.t("resolve  SPI config file [ {} ] with load class", spiConfigUrl);
          if (spiConfigUrl.getName().replace(File.separator, SEPARATOR).contains(strategy.directory())) {
            loadResource(
                    spiClasses,
                    classPathScanner.getClassLoader(),
                    spiInterfaceClass,
                    spiConfigUrl,
                    strategy);
          }
        }

      } catch (Throwable t) {
        LOG.e(
            "Exception occurred when loading SPI class (interface: " + spiInterfaceClass + ").", t);
      }
      //      loadDirectory(spiClasses, strategy, spiInterfaceClass);
    }

    return spiClasses;
  }

  /**
   * 保存SPIDefinition
   *
   * @param spiInterfaceClass
   * @param spiName
   * @param spiInstanceClass
   * @param strategy
   */
  private void saveSPIDefinition(
      Class<?> spiInterfaceClass,
      String spiName,
      Class<?> spiInstanceClass,
      LoadStrategy strategy) {
    SPIRole spiRole = strategyMap.getOrDefault(strategy.getClass(), SPIRole.NORMAL_SPI);
    final List<SPIDefinition> definitionList = getSPIDefinitionList(spiInterfaceClass);
    // 判断去除多于加载
    if (definitionList.isEmpty()) {
      createSPIDefinition(spiInterfaceClass, spiName, spiInstanceClass, spiRole, definitionList);
    } else {
      SPIDefinition exists = getSpiDefinition(spiInterfaceClass, spiName);
      if (exists == null) {
        createSPIDefinition(spiInterfaceClass, spiName, spiInstanceClass, spiRole, definitionList);
      } else if (strategy.overridden() && exists.getRole().equals(spiRole)) {
        createSPIDefinition(spiInterfaceClass, spiName, spiInstanceClass, spiRole, definitionList);
      }
    }
  }

  /**
   * 创建SPIDefinition
   *
   * @param spiInterfaceClass
   * @param spiName
   * @param spiInstanceClass
   * @param spiRole
   * @param definitionList
   */
  private void createSPIDefinition(
      Class<?> spiInterfaceClass,
      String spiName,
      Class<?> spiInstanceClass,
      SPIRole spiRole,
      List<SPIDefinition> definitionList) {
    SPIDefinition definition = SPIDefinitionBuilder.build(spiName, spiInstanceClass, spiRole);
    definitionList.add(definition);
    LOG.t("save SPI class: {}", spiInstanceClass);
    SPI_DEFINITIONS.put(spiInterfaceClass, definitionList);
  }

  /**
   * @param spiInterfaceClass
   * @param spiName
   * @param spiInstanceClass
   * @return
   */
  private boolean containSPIDefinition(
      Class<?> spiInterfaceClass, String spiName, Class<?> spiInstanceClass) {
    if (!containSPIDefinition(spiInterfaceClass)) {
      return false;
    }
    if (StrUtils.isBlank(spiName)) {
      return false;
    }
    if (Objects.isNull(spiInstanceClass)) {
      return false;
    }
    SPIDefinition spiDefinition = getSpiDefinition(spiInterfaceClass, spiName);
    if (Objects.isNull(spiDefinition)) {
      return false;
    } else if (!spiDefinition.getSPIClass().equals(spiInstanceClass)) {
      return false;
    }
    return true;
  }

  /**
   * @param spiClass 接口类或者接口的实例
   * @param spiName
   * @return
   */
  private boolean containSPIDefinition(Class<?> spiClass, String spiName) {
    if (!containSPIDefinition(spiClass)) {
      return false;
    }
    if (StrUtils.isBlank(spiName)) {
      return false;
    }
    SPIDefinition spiDefinition = getSpiDefinition(spiClass, spiName);
    if (Objects.isNull(spiDefinition)) {
      return false;
    }
    return true;
  }

  private boolean containSPIDefinition(Class<?> spiInterfaceClass) {
    if (Objects.isNull(spiInterfaceClass)) {
      return false;
    }
    List<SPIDefinition> spiDefinitions = getSPIDefinitionList(spiInterfaceClass);
    if (Objects.isNull(spiDefinitions) || spiDefinitions.isEmpty()) {
      return false;
    }
    return true;
  }

  @Deprecated
  private void loadDirectory(
      Map<String, Class<?>> spiClasses, LoadStrategy strategy, Class<?> spiInterfaceClass) {
    String fileName = strategy.directory() + spiInterfaceClass.getName();
    try {
      Enumeration<URL> urls = null;
      ClassLoader classLoader = FactoryUtils.findClassLoader();

      // try to load from SPIFactory's ClassLoader first
      if (strategy.preferSpiClassLoader()) {
        ClassLoader spiFactoryClassLoader = SPIFactory.class.getClassLoader();
        if (ClassLoader.getSystemClassLoader() != spiFactoryClassLoader) {
          urls = spiFactoryClassLoader.getResources(fileName);
        }
      }

      if (urls == null || !urls.hasMoreElements()) {
        if (classLoader != null) {
          urls = classLoader.getResources(fileName);
        } else {
          urls = ClassLoader.getSystemResources(fileName);
        }
      }

      if (urls != null) {
        while (urls.hasMoreElements()) {
          java.net.URL resourceURL = urls.nextElement();
          //          loadResource(spiClasses, classLoader, spiInterfaceClass, resourceURL,
          // strategy);
        }
      }
    } catch (Throwable t) {
      LOG.e(
          "Exception occurred when loading SPI class (interface: "
              + spiInterfaceClass
              + ", description file: "
              + fileName
              + ").",
          t);
    }
  }

  /**
   * 读取并解析SPI配置文件s
   *
   * @param spiClasses
   * @param classLoader
   * @param spiInterfaceClass
   * @param resource
   * @param strategy
   */
  private void loadResource(
      Map<String, Class<?>> spiClasses,
      ClassLoader classLoader,
      Class<?> spiInterfaceClass,
      ClassPathScanner.Resource resource,
      LoadStrategy strategy) {
    try {
      try (BufferedReader reader =
          new BufferedReader(
              new InputStreamReader(resource.getInputStream(), StandardCharsets.UTF_8))) {
        String line;
        String spiInstanceName = null;
        while ((line = reader.readLine()) != null) {
          final int ci = line.indexOf('#');
          if (ci >= 0) {
            line = line.substring(0, ci);
          }
          line = line.trim();
          if (line.length() > 0) {
            try {
              String spiName = null;
              int i = line.indexOf('=');
              if (i > 0) {
                spiName = line.substring(0, i).trim();
                spiInstanceName = line.substring(i + 1).trim();
              } else {
                spiInstanceName = line;
              }
              if (StrUtils.isNotEmpty(spiInstanceName)
                  && !isExcluded(spiInstanceName, strategy.directory())) {
                loadClass(
                    spiClasses,
                    resource,
                    spiInterfaceClass,
                    ClassUtils.forName(spiInstanceName, true, classLoader),
                    spiName,
                    strategy);
              }
            } catch (Throwable t) {
              t.printStackTrace();
              CommonException e =
                  new CommonException(
                      "Failed to load SPI class (interface: "
                          + spiInterfaceClass
                          + ", class line: "
                          + line
                          + ") in "
                          + resource.getName()
                          + ", cause: "
                          + t.getMessage(),
                      t);
              exceptions.put(line, e);
            }
          }
        }
      }
    } catch (Throwable t) {
      LOG.e(
          "Exception occurred when loading SPI class (interface: "
              + spiInterfaceClass
              + ", class file: "
              + resource.getName()
              + ") in "
              + resource.getName(),
          t);
    }
  }

  private boolean isExcluded(String className, String... excludedPackages) {
    if (excludedPackages != null) {
      for (String excludePackage : excludedPackages) {
        if (className.startsWith(excludePackage + ".")) {
          return true;
        }
      }
    }
    return false;
  }

  /**
   * 加载SPI实例CLass
   *
   * @param spiClasses
   * @param resource
   * @param spiInterfaceClass
   * @param spiInstanceClass
   * @param name
   * @param strategy
   * @throws NoSuchMethodException
   */
  private void loadClass(
      Map<String, Class<?>> spiClasses,
      ClassPathScanner.Resource resource,
      Class<?> spiInterfaceClass,
      Class<?> spiInstanceClass,
      String name,
      LoadStrategy strategy)
      throws NoSuchMethodException {
    if (StrUtils.isBlank(name)) {
      name = this.createSpiName(spiInterfaceClass, spiInstanceClass);
      if (name.length() == 0) {
        throw new CommonException(
            "No such SPI name for the class "
                + spiInstanceClass.getName()
                + " in the config "
                + resource.getName());
      }
    }
    if (!spiInterfaceClass.isAssignableFrom(spiInstanceClass)) {
      throw new CommonException(
          "Error occurred when loading SPI class (interface: "
              + spiInterfaceClass
              + ", class line: "
              + spiInstanceClass.getName()
              + "), class "
              + spiInstanceClass.getName()
              + " is not subtype of interface.");
    }
    if (FactoryUtils.withWrapperAnnotation(spiInstanceClass)&&isWrapperClass(spiInstanceClass, spiInterfaceClass)) {
      cacheWrapperClass(spiInstanceClass);
    } else {
      String[] names = NAME_SEPARATOR.split(name);
      if (ArrayUtils.isNotEmpty(names)) {
        for (String n : names) {
          saveInSpiClass(spiClasses, spiInterfaceClass, spiInstanceClass, n, strategy);
        }
      }
    }
    saveSPIDefinition(spiInterfaceClass, name, spiInstanceClass, strategy);
  }

  /** cache name */
  @Deprecated
  private void cacheName(Class<?> clazz, String name) {
    if (!cachedSpiNames.containsKey(name) && !cachedSpiNames.containsValue(clazz)) {
      cachedSpiNames.put(name, clazz);
    } else if (clazz != cachedSpiNames.get(name)) {
      String duplicateMsg =
          "SPI"
              + name
              + " already save another SPI interface "
              + cachedSpiNames.get(name).getName()
              + " current SPI interface "
              + clazz.getName();
      LOG.w(duplicateMsg);
      throw new CommonException(duplicateMsg);
    }
  }

  /** put clazz in spiClasses */
  private void saveInSpiClass(
      Map<String, Class<?>> spiClasses,
      Class<?> spiInterfaceClass,
      Class<?> spiInstanceClass,
      String spiName,
      LoadStrategy strategy) {
    Class<?> c = spiClasses.get(spiName);
    if (c == null || strategy.overridden()) {
      spiClasses.put(spiName, spiInstanceClass);
    } else if (c != spiInstanceClass) {
      // duplicate implementation is unacceptable
      unacceptableExceptions.add(spiName);
      String duplicateMsg =
          "Duplicate SPI "
              + spiInterfaceClass.getName()
              + " name "
              + spiName
              + " on "
              + c.getName()
              + " and "
              + spiInstanceClass.getName();
      LOG.e(duplicateMsg);
      throw new CommonException(duplicateMsg);
    }
  }

  /** cache Adaptive class which is annotated with <code>Adaptive</code> */
  @Deprecated
  private void cacheAdaptiveClass(Class<?> spiInterfaceClass,Class<?> adaptiveClass, boolean overridden) {
    if (!CACHED_ADAPTIVE_CLASS_MAP.containsKey(adaptiveClass) || overridden) {
      CACHED_ADAPTIVE_CLASS_MAP.put(spiInterfaceClass,adaptiveClass);
    } else {
      throw new CommonException(
          "More than 1 adaptive class found: " + adaptiveClass.getName());
    }
  }

  @SuppressWarnings("unchecked")
  private <T> T doGetAdaptiveSpi(Class<T> adaptiveInterfaceClass) {
    if (!FactoryUtils.withAdaptiveAnnotation(adaptiveInterfaceClass.getMethods())) {
      throw new IllegalArgumentException(
          "SPI type ("
              + adaptiveInterfaceClass
              + ") is not an Adaptive class or no Adaptive method, because it is NOT annotated with @"
              + Adaptive.class.getSimpleName()
              + "!");
    }
    Object instance = SPI_ADAPTIVE_INSTANCES.get(adaptiveInterfaceClass);
    if (instance == null) {
      try {
        // 创建对象
        instance = createAdaptiveSpiInstance(adaptiveInterfaceClass);
        // 注入对象
        SPIDefinition adaptiveSpiDefinition = getAdaptiveSpiDefinition(adaptiveInterfaceClass);
        injectSpiWrapInstance(adaptiveSpiDefinition, injectSpiInstance(instance,adaptiveSpiDefinition), true);
      } catch (Throwable t) {
        t.printStackTrace();
//        throw new CommonException("Failed to create adaptive instance: " + t, t);
      }
    }
    return (T) instance;
  }

  @SuppressWarnings("unchecked")
  private Object createAdaptiveSpiInstance(Class<?> adaptiveInterfaceClass) {
    if (!containSPIDefinition(adaptiveInterfaceClass)) {
      loadSpiClasses(adaptiveInterfaceClass);
    }
    try {
      if (SPI_ADAPTIVE_INSTANCES.containsKey(adaptiveInterfaceClass)) {
        return SPI_ADAPTIVE_INSTANCES.get(adaptiveInterfaceClass);
      } else {
        SPIDefinition spiDefinition = createAdaptiveSpiClass(adaptiveInterfaceClass);
        Object spiInstance = createSpiInstance(spiDefinition);
        SPI_ADAPTIVE_INSTANCES.put(adaptiveInterfaceClass, spiInstance);
        return spiInstance;
      }
    } catch (Exception e) {
      throw new CommonException(
          "Can't create adaptive SPI " + adaptiveInterfaceClass + ", cause: " + e.getMessage(), e);
    }
  }

  private SPIDefinition createAdaptiveSpiClass(Class<?> adaptiveInterfaceClass) {

    String adaptiveSpiName = createAdaptiveSpiName(adaptiveInterfaceClass);
    if (containSPIDefinition(adaptiveInterfaceClass, adaptiveSpiName)) {
      return getSpiDefinition(adaptiveInterfaceClass, adaptiveSpiName);
    }

    ClassLoader classLoader = FactoryUtils.findClassLoader();
    Compiler compiler = doGetSpi(Compiler.class, Compiler.DEFAULT_SPI_NAME);
    if (compiler instanceof SpiAdaptiveClassAsmCompiler) {
      Class<?> adaptiveClass = compiler.compile(adaptiveInterfaceClass.getName(), classLoader);
      doAddSpiDefinition(adaptiveSpiName, adaptiveInterfaceClass, adaptiveClass);
    } else {
      String code =
          new AdaptiveClassCodeGenerator(
                  adaptiveInterfaceClass, createSpiName(adaptiveInterfaceClass))
              .generate();
      Class<?> adaptiveClass = compiler.compile(code, classLoader);
      doAddSpiDefinition(adaptiveSpiName, adaptiveInterfaceClass, adaptiveClass);
    }
    return getSpiDefinition(adaptiveInterfaceClass, adaptiveSpiName);
  }

  /**
   * 一般是内部使用
   * @param instanceClass
   */
  private void doAddSpiDefinition(String spiName, Class<?> instanceClass){
    Class<?> interfaceClass = getInterfaceClass(instanceClass);
    doAddSpiDefinition(spiName,interfaceClass,instanceClass);
  }

  /**
   * 添加spi具体执行方法
   *
   * @param name
   * @param spiInterfaceClass
   * @param spiInstanceClass
   */
  private void doAddSpiDefinition(String name, Class<?> spiInterfaceClass, Class<?> spiInstanceClass) {
    if (!spiInterfaceClass.isAssignableFrom(spiInstanceClass)) {
      throw new CommonException(
          "Input type " + spiInstanceClass + " doesn't implement the SPI " + spiInterfaceClass);
    }
    if (!spiInterfaceClass.isInterface()) {
      throw new CommonException("Input type " + spiInterfaceClass + " can't be interface!");
    }

    if (StrUtils.isBlank(name)) {
      throw new CommonException("SPI name is blank (SPI " + spiInterfaceClass + ")!");
    }

//    cacheName(spiInstanceClass, name);

    if (isWrapperClass(spiInstanceClass, spiInterfaceClass)) {
      cacheWrapperClass(spiInstanceClass);
    }
    saveSPIDefinition(spiInterfaceClass, name, spiInstanceClass, new SPILoadStrategy());
  }

  private Object applyBeanPostProcessorsBeforeInitialization(Object existingSpi, SPIDefinition spiDefinition) throws CommonException {
    Object result = existingSpi;
    Object current;
    for (Iterator var4 = this.getSpiPostProcessorList().iterator(); var4.hasNext(); result = current) {
      SpiPostProcessor processor = (SpiPostProcessor) var4.next();
      current = processor.postProcessBeforeInitialization(result, spiDefinition);
      if (current == null) {
        return result;
      }
    }

    return result;
  }

  private Object applyBeanPostProcessorsAfterInitialization(Object existingSpi, SPIDefinition spiDefinition) throws CommonException {
    Object result = existingSpi;
    Object current;
    for (Iterator var4 = this.getSpiPostProcessorList().iterator(); var4.hasNext(); result = current) {
      SpiPostProcessor processor = (SpiPostProcessor) var4.next();
      current = processor.postProcessAfterInitialization(result, spiDefinition);
      if (current == null) {
        return result;
      }
    }

    return result;
  }

  @Override
  public String toString() {
    return this.getClass().getName();
  }

  @Override
  public void addSPI(String name, Class<?> spiInterfaceClass, Class<?> spiInstanceClass) {
    doAddSpiDefinition(name, spiInterfaceClass, spiInstanceClass);
  }

  @Override
  @SuppressWarnings("unchecked")
  public <T> T getSPI(Class<T> spiInterfaceClass, String name) {
    return doGetSpi(spiInterfaceClass, name);
  }

  @Override
  public <T> T getSPI(Class<T> type) {
    return getSPI(type, createSpiName(type));
  }

  @Override
  public <T> T getAdaptiveSPI(Class<T> type) {
    return doGetAdaptiveSpi(type);
  }

  @Override
  public Map<String, Class<?>> getSPIClassMap(Class<?> type) {
    return doGetSPIMap(type);
  }

  @Override
  public String getSPIName(Class<?> type) {
    return getSpiNameBySpiInstance(type);
  }

  @Override
  public void autowireSPI(java.lang.Object spi) {
    doInjectSpi(spi,true);
  }

  @Override
  public void destroySPI(Class<?> type, String name) {
    SPI_INSTANCES.remove(type);
    SPI_ADAPTIVE_INSTANCES.remove(type);
  }

  @Override
  public void destroyAllSPI(String name) {
    SPI_INSTANCES.clear();
    SPI_ADAPTIVE_INSTANCES.clear();
  }

  /** 构造器注入元数据 */
  @Deprecated
  static class ConstructorInjectMetaData {

    private Constructor<?> constructor;

    private List<ParameterInjectMetaData> metaDataList;

    private Object[] parameters;

    public ConstructorInjectMetaData(Constructor<?> constructor, List<ParameterInjectMetaData> metaDataList, Object[] parameters) {
      this.constructor = constructor;
      this.metaDataList = metaDataList;
      this.parameters = parameters;
    }

    public Constructor<?> getConstructor() {
      return constructor;
    }

    public List<ParameterInjectMetaData> getMetaDataList() {
      return metaDataList;
    }
  }

  @Deprecated
  static class ParameterInjectMetaData {
    private Class<?> spiClass;

    private String spiName;

    public ParameterInjectMetaData(Class<?> spiClass, String spiName) {
      this.spiClass = spiClass;
      this.spiName = spiName;
    }

    public Class<?> getSpiClass() {
      return spiClass;
    }

    public String getSpiName() {
      return spiName;
    }
  }
}
